﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Xna.Framework.Audio;
using System.Windows.Media.Imaging;
using SignalLab.BaseLibrary;
using SignalLab.Analysers;
using System.IO.IsolatedStorage;
using System.Diagnostics;

namespace SignalLab
{
  public partial class Analyser : PhoneApplicationPage
  {

    XNAAsyncDispatcher xnaDispatcher;
    BpmAnalyser analyser;
    Microphone mic;

    PagedArray<byte> record;

    #region pomocne properties pre vykreslovanie
    byte[] buffer;
    int width;
    int height = byte.MaxValue;
    int buffersPerScreen;
    int samplesPerPixel;
    WriteableBitmap b;
    #endregion

    public Analyser()
    {
      InitializeComponent();
      this.Loaded += new RoutedEventHandler(Analyser_Loaded);
      this.Unloaded += new RoutedEventHandler(Analyser_Unloaded);



      this.DataContext = new AnalyserViewModel(); ;
    }

    void Analyser_Loaded(object sender, RoutedEventArgs e)
    {



      xnaDispatcher = new XNAAsyncDispatcher(TimeSpan.FromMilliseconds(50));
      xnaDispatcher.StartUpdating();

      mic = Microphone.Default;
      mic.BufferReady += mic_BufferReady;
      mic.BufferDuration = TimeSpan.FromMilliseconds(200);

      buffer = new byte[mic.GetSampleSizeInBytes(mic.BufferDuration)];
      buffersPerScreen = 10;//2 sekundy

      width = (int)((FrameworkElement)visualiserImg.Parent).ActualWidth;
      currentBuffer = 0;
      samplesPerPixel = buffer.Length * buffersPerScreen / Helper.BYTES_PER_SAMPLE / width;
      x = 0;

      analyser = new BpmAnalyser(mic.SampleRate, 16, buffer.Length);

      foreach (var property in analyser.GetProperties())
        ((AnalyserViewModel)DataContext).Properties.Add(property);

      mic.Start();

    }

    void Analyser_Unloaded(object sender, RoutedEventArgs e)
    {
      mic.Stop();
      mic.BufferReady -= mic_BufferReady;
      if (((AnalyserViewModel)DataContext).IsRecording)
      {
        analyser.Stop();
      }
      xnaDispatcher.StopUpdating();
    }


    
    const int alpha = 255 << 24;


    private void ToggleButton_Checked(object sender, RoutedEventArgs e)
    {

      analyser.Start();
      isFirst = 3;
      ((AnalyserViewModel)DataContext).IsRecording = true;

      record = new PagedArray<byte>(buffer.Length);
      var anim = (Storyboard)Resources["PulseLogo"];
      anim.Begin();
      
    }

    private void ToggleButton_Unchecked(object sender, RoutedEventArgs e)
    {
      ((AnalyserViewModel)DataContext).IsRecording = false;
      buffer = new byte[mic.GetSampleSizeInBytes(mic.BufferDuration)];
      analyser.Stop();
      var anim = (Storyboard)Resources["PulseLogo"];
      anim.Stop();

      var result = MessageBox.Show("Do you want to save signal wave?", "Signal Lab", MessageBoxButton.OKCancel);

      var dialog = new SaveToCategory();
      App.ShowModal(dialog, el =>
      {
        string category = (el as SaveToCategory).Category;

      });

      if (result == MessageBoxResult.OK)
      {
        int i = 0;
        string filePrefix = "Record ";

        foreach(string fileName in AppManager.Instance.GetRecords())
        {
          if (fileName.StartsWith(filePrefix) && fileName.Length > filePrefix.Length)
          {
            int num;
            if (int.TryParse(fileName.Substring(filePrefix.Length, fileName.Length - filePrefix.Length), out num))
            {
              if (i < num) i = num;
            }
          }
        }
        i++;

        var guid = Guid.NewGuid();

        var userStore = IsolatedStorageFile.GetUserStoreForApplication();

        using (var fs = userStore.CreateFile(filePrefix + i.ToString()))
        {
          WavHelper.WriteWavHeader(fs, record.Count, mic.SampleRate, Helper.BYTES_PER_SAMPLE * 8, 1);
          foreach(byte[] page in record.GetPages())
          {
            WavHelper.AppendPcmToWav(fs, page);
          }
        }

      }
    }


    int x;
    int currentBuffer;

    int isFirst;

    void mic_BufferReady(object sender, EventArgs e)
    {
      if (((AnalyserViewModel)DataContext).IsRecording)
      {
        buffer = new byte[mic.GetSampleSizeInBytes(mic.BufferDuration)];
      }
      mic.GetData(buffer);

      if (isFirst > 0)
      {
        Debug.WriteLine(string.Format("{0} {1} {2}", buffer[0], buffer[2], buffer[4]));
        isFirst--;
      }

      if (((AnalyserViewModel)DataContext).IsRecording)
      {
        record.AddPage(buffer);
      }

      analyser.SendData(buffer);
      
      double zoom = height / (double)ushort.MaxValue;

      if (currentBuffer == 0) b = new WriteableBitmap(width, height);      

      int bufferPos = 0;
      while(bufferPos < buffer.Length && x < width)
      {
        for (int j = 0; j < samplesPerPixel; j++)
        {
          var sample = Helper.GetSampleAtPosition(buffer, bufferPos);
          int y = (int)(sample * zoom) + height / 2;
          b.Pixels[y * width + x] = alpha | (255 << 16);
          bufferPos += Helper.BYTES_PER_SAMPLE;
          if (bufferPos >= buffer.Length) break;
        }
        x++;
      }
      currentBuffer++;
      if (currentBuffer >= buffersPerScreen)
      {
        x = 0;
        currentBuffer = 0;
      }

      b.Invalidate();
      visualiserImg.Source = b;


    }
  }
}